package com.ruixi.service.impl;

import com.ruixi.enums.DecimalTypeEnum;
import com.ruixi.enums.SeqTypeEnum;
import com.ruixi.enums.SystemErrorCode;
import com.ruixi.exception.PayException;
import com.ruixi.handler.SequenceHandler;
import com.ruixi.mapper.SequenceMapper;
import com.ruixi.service.SequenceService;
import com.ruixi.utils.AssertUtils;
import com.ruixi.utils.HexConvertorUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author lrzg
 * @date 2021-05-12 14:43
 * @Description TODO
 */
@Service
public class SequenceServiceImpl implements SequenceService, InitializingBean {
    private static final Logger logger = LoggerFactory.getLogger(SequenceServiceImpl.class);

    private Map<String,SequenceHandler> seqHandlerMap = new ConcurrentHashMap<>();
    /**
     * 流水数据库操作Mapper
     */
    @Autowired
    private SequenceMapper sequenceMapper;


    @Override
    public String generate(SeqTypeEnum seqType) {
        logger.info("开始生成流水号");
        AssertUtils.isNotNull(seqType, SystemErrorCode.BIZ_PARAM_NULL);
        String seq = seqType.getCode() + generate(seqType, 8, DecimalTypeEnum.DECIMAL,true);
        logger.info("结束生成流水号:{}", seq);
        return seq;
    }
    @Override
    public String generate(SeqTypeEnum seqType, int seqLen, DecimalTypeEnum decimalType,boolean isDate) {
        AssertUtils.isNotNull(seqType, SystemErrorCode.BIZ_PARAM_NULL);
        AssertUtils.isTrue(seqLen > 1, SystemErrorCode.BIZ_PARAM_NULL);
        String seq = generateSeq(seqType, seqLen, decimalType);
        if (StringUtils.isBlank(seq) || seq.length() > seqLen) {
            logger.error("流水({})生成错误.", seq);
            throw new PayException(SystemErrorCode.SEQUENCE_GEN_ERR);
        }
        if(isDate){
            SequenceHandler handler = seqHandlerMap.get(seqType.code());
            return handler.getCurrentDate()+seq;
        }else {
            return seq;
        }

    }
    /**
     * @Description 流水号生成
     * @Params
     * @Return
     * @Exceptions
     */
    private String generateSeq(SeqTypeEnum seqType, int seqLen, DecimalTypeEnum decimalType) {
        long decimal = -1L;
        SequenceHandler handler = seqHandlerMap.get(seqType.code());
        AssertUtils.isNotNull(handler, SystemErrorCode.SYSTEM_ERROR);
        decimal = handler.getSeq();
        logger.debug("decimal:"+decimal);
        String hexStr = HexConvertorUtil.transform(decimal, Integer.valueOf(decimalType.getCode()));
        logger.debug("hexStr:"+hexStr);
        return StringUtils.leftPad(hexStr, seqLen, "0");
    }

    /**
     * 项目启动的时候初始化
     * @throws Exception
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        logger.debug("初始化Bean");
        for (SeqTypeEnum type : SeqTypeEnum.values()) {
            SequenceHandler handler = new SequenceHandler(sequenceMapper, type);
            seqHandlerMap.put(type.code(), handler);
        }

    }
}
